package com.butterfly.hotkey.client.core.service;


import cn.hutool.core.collection.CollUtil;
import com.butterfly.hotkey.client.core.Refreshable;
import com.butterfly.hotkey.client.core.config.AppClientProperties;
import com.butterfly.hotkey.core.cache.CacheFactory;
import com.butterfly.hotkey.core.cache.ICacheManager;
import com.butterfly.hotkey.core.constant.Constants;
import com.butterfly.hotkey.core.constant.NumConst;
import com.butterfly.hotkey.core.enums.CacheDurationEnum;
import com.butterfly.hotkey.core.model.AppCacheModel;
import com.butterfly.hotkey.core.rule.ClientKeyRule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @author butterfly
 * @version 1.0
 */
public class HotkeyCacheService implements Refreshable {

    private static final Logger log = LoggerFactory.getLogger(Constants.CLIENT);

    /**
     * 包含每个缓存时长的缓存，避免MAP量太大，只提供指定的缓存级别
     * key - duration
     * value - 对应延时长度的缓存
     *
     * @see CacheDurationEnum
     */
    private final static Map<String, ICacheManager> CACHE_MAP = new ConcurrentHashMap<>(NumConst.SIXTEEN);

    private final AppClientProperties clientProperties;

    public HotkeyCacheService(AppClientProperties clientProperties) {
        this.clientProperties = clientProperties;
        refresh();
    }

    @Override
    public void refresh() {
        List<ClientKeyRule> clientKeyRules = clientProperties.getClientKeyRules();
        if (CollUtil.isEmpty(clientKeyRules)) {
            clearCache();
            return;
        }
        Set<String> durationSet = clientKeyRules.stream()
                .map(ClientKeyRule::getDuration)
                .collect(Collectors.toSet());
        // 删除无需使用的缓存信息
        for (Map.Entry<String, ICacheManager> entry : CACHE_MAP.entrySet()) {
            String mapDuration = entry.getKey();
            if (!durationSet.contains(mapDuration)) {
                entry.getValue().clear();
            }
        }

        AppCacheModel appCache = clientProperties.getCache();
        for (ClientKeyRule clientKeyRule : clientKeyRules) {
            String duration = clientKeyRule.getDuration();
            if (CACHE_MAP.containsKey(duration)) {
                continue;
            }
            // 构建新的缓存数据
            int expireSeconds = CacheDurationEnum.getSeconds(duration);
            AppCacheModel config = AppCacheModel.Builder.builder()
                    .initialCapacity(appCache.getInitialCapacity())
                    .maximumSize(appCache.getMaximumSize())
                    .build();
            ICacheManager cache = CacheFactory.buildCache(config, expireSeconds);
            CACHE_MAP.put(duration, cache);
            log.info("build hotkey duration:{} cache", duration);
        }
    }

    public ICacheManager getCache(String duration) {
        return CACHE_MAP.get(duration);
    }

    private void clearCache() {
        for (Map.Entry<String, ICacheManager> entry : CACHE_MAP.entrySet()) {
            ICacheManager value = entry.getValue();
            value.clear();
        }
    }

}
